package org.beetlframework.mvc;

import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.beetlframework.util.BeanUtil;




/**
 * 请求参数工具类
 * @author 草原狼
 * @date 2016-10-4
 */
public class RequestParam {
	/**
	 * 获取请求参数
	 * @param name
	 * @return
	 */
	public static String getParam(String name){		
		return ServletActionContext.getRequest().getParameter(name);
	}
	
	/**
	 * Returns the value of a request parameter as a String, or default value if the parameter does not exist.
	 * @param name a String specifying the name of the parameter
	 * @param defaultValue a String value be returned when the value of parameter is null
	 * @return a String representing the single value of the parameter
	 */
	public static String getPara(String name, String defaultValue) {
		String result = getParam(name);
		return result != null && !"".equals(result) ? result : defaultValue;
	}
	
	/**
	 * Returns the values of the request parameters as a Map.
	 * @return a Map contains all the parameters name and value
	 */
	public static Map<String, String[]> getParaMap() {
		return ServletActionContext.getRequest().getParameterMap();
	}
	
	/**
	 * Returns an Enumeration of String objects containing the names of the parameters
	 * contained in this request. If the request has no parameters, the method returns
	 * an empty Enumeration.
	 * @return an Enumeration of String objects, each String containing the name of 
	 * 			a request parameter; or an empty Enumeration if the request has no parameters
	 */
	public static Enumeration<String> getParaNames() {
		return ServletActionContext.getRequest().getParameterNames();
	}
	
	/**
	 * Returns an array of String objects containing all of the values the given request 
	 * parameter has, or null if the parameter does not exist. If the parameter has a 
	 * single value, the array has a length of 1.
	 * @param name a String containing the name of the parameter whose value is requested
	 * @return an array of String objects containing the parameter's values
	 */
	public static String[] getParaValues(String name) {
		return ServletActionContext.getRequest().getParameterValues(name);
	}
	
	/**
	 * Returns an array of Integer objects containing all of the values the given request 
	 * parameter has, or null if the parameter does not exist. If the parameter has a 
	 * single value, the array has a length of 1.
	 * @param name a String containing the name of the parameter whose value is requested
	 * @return an array of Integer objects containing the parameter's values
	 */
	public static Integer[] getParaValuesToInt(String name) {
		String[] values = ServletActionContext.getRequest().getParameterValues(name);
		if (values == null)
			return null;
		Integer[] result = new Integer[values.length];
		for (int i=0; i<result.length; i++)
			result[i] = Integer.parseInt(values[i]);
		return result;
	}
	
	public static Long[] getParaValuesToLong(String name) {
		String[] values = ServletActionContext.getRequest().getParameterValues(name);
		if (values == null)
			return null;
		Long[] result = new Long[values.length];
		for (int i=0; i<result.length; i++)
			result[i] = Long.parseLong(values[i]);
		return result;
	}
	
	/**
	 * Returns an Enumeration containing the names of the attributes available to this request.
	 * This method returns an empty Enumeration if the request has no attributes available to it. 
	 * @return an Enumeration of strings containing the names of the request's attributes
	 */
	public static Enumeration<String> getAttrNames() {
		return ServletActionContext.getRequest().getAttributeNames();
	}
	
	/**
	 * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
	 * @param name a String specifying the name of the attribute
	 * @return an Object containing the value of the attribute, or null if the attribute does not exist
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getAttr(String name) {
		return (T) ServletActionContext.getRequest().getAttribute(name);
	}
	
	/**
	 * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
	 * @param name a String specifying the name of the attribute
	 * @return an Integer Object containing the value of the attribute, or null if the attribute does not exist
	 */
	public static Integer getAttrForInt(String name) {
		return (Integer)ServletActionContext.getRequest().getAttribute(name);
	}
	
	private static Boolean toBoolean(String value, Boolean defaultValue) {
		if (value == null || "".equals(value.trim()))
			return defaultValue;
		value = value.trim().toLowerCase();
		if ("1".equals(value) || "true".equals(value))
			return Boolean.TRUE;
		else if ("0".equals(value) || "false".equals(value))
			return Boolean.FALSE;
		throw new RuntimeException("参数转换为Boolean类型失败");
	}
	
	/**
	 * Returns the value of a request parameter and convert to Boolean.
	 * @param name a String specifying the name of the parameter
	 * @return true if the value of the parameter is "true" or "1", false if it is "false" or "0", null if parameter is not exists
	 */
	public static Boolean getParaToBoolean(String name) {
		return toBoolean(ServletActionContext.getRequest().getParameter(name), null);
	}
	
	
	/**
	 * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
	 * @param name a String specifying the name of the attribute
	 * @return an String Object containing the value of the attribute, or null if the attribute does not exist
	 */
	public static String getAttrForStr(String name) {
		return (String)ServletActionContext.getRequest().getAttribute(name);
	}	
	/**
	 * 获取int类型参数
	 */
	public static Integer getIntParam(String name){
		String str = getParam(name);		
		return Integer.parseInt(str);
	}
	/**
	 * 获取int类型参数，带默认值
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	public static Integer getIntParam(String name,Integer defaultValue){
		Integer result = null;
		try{
			result = getIntParam(name);	
		}catch(Exception e){
			//TODO 需要输出到日志
		}			
		return result != null ? result : defaultValue;
	}
	/**
	 * 获取long型参数
	 * @param name
	 * @return
	 */
	public static Long getLongParam(String name){
		String str = getParam(name);
		return Long.parseLong(str);
	}
	/**
	 * 获取long型参数，带默认值
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	public static Long getLongParam(String name,Long defaultValue){
		Long result = null;
		try{
			result = getLongParam(name);	
		}catch(Exception e){
			//TODO 需要输出到日志
		}			
		return result != null ? result : defaultValue;
	}
	/**
	 * Stores an attribute in this request
	 * @param name a String specifying the name of the attribute
	 * @param value the Object to be stored
	 */
	public static void setAttr(String name, Object value) {
		ServletActionContext.getRequest().setAttribute(name, value);		
	}
	
	/**
	 * Removes an attribute from this request
	 * @param name a String specifying the name of the attribute to remove
	 */
	public static void removeAttr(String name) {
		ServletActionContext.getRequest().removeAttribute(name);		
	}
	
	/**
	 * Stores attributes in this request, key of the map as attribute name and value of the map as attribute value
	 * @param attrMap key and value as attribute of the map to be stored
	 */
	public static void setAttrs(Map<String, Object> attrMap) {
		HttpServletRequest request = ServletActionContext.getRequest();
		for (Map.Entry<String, Object> entry : attrMap.entrySet()){
			request.setAttribute(entry.getKey(), entry.getValue());
		}		
	}
	
	/**
	 * Return true if the para value is blank otherwise return false
	 */
	public static boolean isParaBlank(String paraName) {
		HttpServletRequest request = ServletActionContext.getRequest();
		String value = request.getParameter(paraName);
		return value == null || value.trim().length() == 0;
	}
	
	/**
	 * Return true if the para exists otherwise return false
	 */
	public static boolean isParaExists(String paraName) {
		HttpServletRequest request = ServletActionContext.getRequest();
		return request.getParameterMap().containsKey(paraName);
	}
	
	private static Date toDate(String value, Date defaultValue) {
		try {
			if (value == null || "".equals(value.trim()))
				return defaultValue;
			return new java.text.SimpleDateFormat("yyyy-MM-dd").parse(value.trim());
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}
	
	/**
	 * Returns the value of a request parameter and convert to Date.
	 * @param name a String specifying the name of the parameter
	 * @return a Date representing the single value of the parameter
	 */
	public static Date getParaToDate(String name) {
		HttpServletRequest request = ServletActionContext.getRequest();
		return toDate(request.getParameter(name), null);
	}
	
	/**
	 * Returns the value of a request parameter and convert to Date with a default value if it is null.
	 * @param name a String specifying the name of the parameter
	 * @return a Date representing the single value of the parameter
	 */
	public static Date getParaToDate(String name, Date defaultValue) {
		HttpServletRequest request = ServletActionContext.getRequest();
		return toDate(request.getParameter(name), defaultValue);
	}
	
	/**
	 * Get cookie value by cookie name.
	 */
	public static String getCookie(String name, String defaultValue) {
		Cookie cookie = getCookieObject(name);
		return cookie != null ? cookie.getValue() : defaultValue;
	}
	
	/**
	 * Get cookie value by cookie name.
	 */
	public static String getCookie(String name) {
		return getCookie(name, null);
	}
	
	/**
	 * Get cookie value by cookie name and convert to Integer.
	 */
	public static Integer getCookieToInt(String name) {
		String result = getCookie(name);
		return result != null ? Integer.parseInt(result) : null;
	}
	
	/**
	 * Get cookie value by cookie name and convert to Integer.
	 */
	public static Integer getCookieToInt(String name, Integer defaultValue) {
		String result = getCookie(name);
		return result != null ? Integer.parseInt(result) : defaultValue;
	}
	
	/**
	 * Get cookie value by cookie name and convert to Long.
	 */
	public static Long getCookieToLong(String name) {
		String result = getCookie(name);
		return result != null ? Long.parseLong(result) : null;
	}
	
	/**
	 * Get cookie value by cookie name and convert to Long.
	 */
	public static Long getCookieToLong(String name, Long defaultValue) {
		String result = getCookie(name);
		return result != null ? Long.parseLong(result) : defaultValue;
	}
	
	/**
	 * Get cookie object by cookie name.
	 */
	public static Cookie getCookieObject(String name) {
		HttpServletRequest request = ServletActionContext.getRequest();
		Cookie[] cookies = request.getCookies();
		if (cookies != null)
			for (Cookie cookie : cookies)
				if (cookie.getName().equals(name))
					return cookie;
		return null;
	}
	
	/**
	 * Get all cookie objects.
	 */
	public static Cookie[] getCookieObjects() {
		HttpServletRequest request = ServletActionContext.getRequest();
		Cookie[] result = request.getCookies();
		return result != null ? result : new Cookie[0];
	}
	
	/**
	 * Set Cookie to response.
	 */
	public static void setCookie(Cookie cookie) {
		HttpServletResponse response = ServletActionContext.getResponse();
		response.addCookie(cookie);		
	}
	
	/**
	 * Set Cookie to response.
	 * @param name cookie name
	 * @param value cookie value
	 * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
	 * @param path see Cookie.setPath(String)
	 */
	public static void setCookie(String name, String value, int maxAgeInSeconds, String path) {
		setCookie(name, value, maxAgeInSeconds, path, null);		
	}
	
	/**
	 * Set Cookie to response.
	 * @param name cookie name
	 * @param value cookie value
	 * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
	 * @param path see Cookie.setPath(String)
	 * @param domain the domain name within which this cookie is visible; form is according to RFC 2109
	 */
	public static void setCookie(String name, String value, int maxAgeInSeconds, String path, String domain) {
		Cookie cookie = new Cookie(name, value);
		if (domain != null)
			cookie.setDomain(domain);
		cookie.setMaxAge(maxAgeInSeconds);
		cookie.setPath(path);
		HttpServletResponse response = ServletActionContext.getResponse();
		response.addCookie(cookie);		
	}
	
	/**
	 * Set Cookie with path = "/".
	 */
	public static void setCookie(String name, String value, int maxAgeInSeconds) {
		setCookie(name, value, maxAgeInSeconds, "/", null);		
	}
	
	/**
	 * Remove Cookie with path = "/".
	 */
	public static void removeCookie(String name) {
		setCookie(name, null, 0, "/", null);		
	}
	
	/**
	 * Remove Cookie.
	 */
	public static void removeCookie(String name, String path) {
		setCookie(name, null, 0, path, null);		
	}
	
	/**
	 * Remove Cookie.
	 */
	public static void removeCookie(String name, String path, String domain) {
		setCookie(name, null, 0, path, domain);		
	}
	
	/**
	 * 根据javaBean类获取实例
	 * @param t
	 * @return
	 */
	public static <T> T getBean(Class<T> t){
		HttpServletRequest request = ServletActionContext.getRequest();
		return BeanUtil.getBean(request,t);
	}

}
